//  Author:
//       Daniel Großer <olav.daniel.grosser@googlemail.com>
//  
//  Copyright (c) 2012 Copyright (C) 2012 by Daniel Großer. This Code is under GNU LGPL 3.0
// 
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
// 
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser General Public License for more details.
// 
//  You should have received a copy of the GNU Lesser General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.

using System;

namespace Beauty
{
    /// <summary>
    /// Use this attribute to mark keywords. Examples for keywords
    /// are: Begin, End, interface... and the like. A keyword must
    /// be followed by a non-letter&non-digit or EOF/EOL. Note: Keywords are
    /// usually ignored, so the Ignore property will be true, because
    /// the value of the keyword is not important for the language.
    /// </summary>
    /// <example>
    /// <code>
    /// [Keyword("Begin")]
    /// public object Begin { get; set; }
    /// </code>
    /// </example>
    public sealed class KeywordAttribute : TerminalAttribute
    {
        /// <summary>
        /// Create a new grammar part that matches a keyword.
        /// </summary>
        /// <param name="keyword">The keyword to match.</param>
        public KeywordAttribute(string keyword)
        {
            StringTerminal = keyword;
            Ignore = true;
        }

        /// <summary>
        /// Get the keyword modelled by this grammar part.
        /// </summary>
        public string Keyword { get { return StringTerminal; } }

        /// <summary>
        /// Try to match the keyword at the very start of a string. The keyword must be followed
        /// by a non-letter/non-digit or EOL/EOF. 
        /// </summary>
        /// <param name="input">The string to match.</param>
        /// <returns>A value greater 0 iff match is successful, where the return value equals the matched length.</returns>
        public override int MatchStart(string input)
        {
            if (input.StartsWith(Keyword, Comparison))
            {
                if (input.Length == Keyword.Length /* EOL/EOF */ || !(char.IsLetterOrDigit(input[Keyword.Length])))
                    return Keyword.Length;
                else
                    return 0;
            }
            else
                return 0;
        }
		
		/// <summary>
		/// Gets the scanner-precedence value. Terminals with a lower
		/// value will be preferred by the scanner. Among a set of
		/// equal-precedence terminals, the longest match will win.
		/// </summary>
		/// <value>
		/// 1, because keywords are less important than delimeters,
		/// but more important than regexes.
		/// </value>
		public override byte ScannerPrecedence { get { return PRECEDENCE; } }		

        /// <summary>
        /// Return a string representation.
        /// </summary>
        /// <returns>The string representation.</returns>
        public override string ToString()
        {
            return string.Format("Keyword \"{0}\"", Keyword);
        }
		
		/// <summary>
		/// The scanner precedence of Keyword Terminals.
		/// </summary>
		public const byte PRECEDENCE = 1;
    }
}
